test_that("Creating a valid `informant` object is possible", {

  tbl <-
    dplyr::tibble(
      a = c(1, 1, 1, 2, 2, 2),
      b = c(5, 5, 5, 3, 6, 3)
    )

  # Create an informant object
  informant <- create_informant(tbl = tbl)

  # Expect that names in an agent object match a
  # prescribed set of names
  expect_true(
    all(
      names(informant) ==
        c("tbl", "read_fn", "tbl_name", "info_label",
          "meta_snippets", "lang", "locale", "metadata"
        )
    )
  )

  # Expect an informant object of class `ptblank_informant`
  expect_s3_class(informant, "ptblank_informant")
  expect_true(is_ptblank_informant(informant))

  # Expect that the `is_ptblank_informant()` returns FALSE
  # for any other type of object
  expect_false(is_ptblank_informant(create_agent(small_table)))
  expect_false(is_ptblank_informant(letters))
  expect_false(is_ptblank_informant(dplyr::tibble(a = 5)))

  # Expect certain classes for the different `ptblank_informant` components
  expect_s3_class(informant$tbl, class(tbl), exact = TRUE)
  expect_null(informant$read_fn)
  expect_type(informant$tbl_name, "character")
  expect_type(informant$info_label, "character")
  expect_type(informant$meta_snippets, "list")
  expect_type(informant$lang, "character")
  expect_type(informant$locale, "character")
  expect_type(informant$metadata, "list")
  expect_type(informant$metadata$table, "list")
  expect_type(informant$metadata$table$name, "character")
  expect_type(informant$metadata$table$`_columns`, "integer")
  expect_type(informant$metadata$table$`_rows`, "double")
  expect_type(informant$metadata$table$`_type`, "character")
  expect_equal(informant$metadata$table$name, "tbl")
  expect_equal(informant$metadata$table$`_columns`, 2)
  expect_equal(informant$metadata$table$`_rows`, 6)
  expect_equal(informant$metadata$table$`_type`, "tbl_df")
  expect_type(informant$metadata$columns, "list")
  expect_equal(names(informant$metadata$columns), c("a", "b"))
  expect_type(informant$metadata$columns$a, "list")
  expect_type(informant$metadata$columns$b, "list")
  expect_equal(names(informant$metadata$columns$a), "_type")
  expect_equal(names(informant$metadata$columns$b), "_type")
  expect_equal(informant$metadata$columns$a$`_type`, "numeric")
  expect_equal(informant$metadata$columns$b$`_type`, "numeric")

  # Expect an error if nothing is provided for
  # either `tbl`, `read_fn`, or `agent`
  expect_error(
    create_informant()
  )

  # Expect an error if both a table and an agent are provided
  expect_error(
    create_informant(
      tbl = small_table,
      agent = create_agent(tbl = small_table)
    )
  )

  # Expect that when a table is piped into `create_informant()`
  # and also when `tbl_name` isn't provided, the table
  # name isn't known so it's assigned as `NA`
  expect_equal(
    small_table %>% create_informant() %>% .$tbl_name,
    NA_character_
  )

  # Expect that using `tbl` to read in a table name but
  # not specifying `tbl_name` results in an autogenerated `tbl_name`
  expect_equal(
    create_informant(tbl = ~ pointblank::small_table) %>% .$tbl_name,
    "~pointblank::small_table"
  )

  # Expect that using `read_fn` to read in a table name but
  # not specifying `tbl_name` results in an `NA` for `tbl_name`; we
  # also expect a warning
  expect_warning(
      obj <- create_informant(read_fn = ~ pointblank::small_table) %>% .$tbl_name,
  )
  expect_equal(obj, NA_character_)

  # Expect that there is a preference for reading a table from
  # a `tbl` if the deprecated `read_fn` is also supplied with a
  # target table; also expect a warning and a message
  expect_message(
    expect_warning(
      informant_2 <- create_informant(
        tbl = tbl,
        read_fn = ~ pointblank::small_table
      )
    )
  )

  expect_equal(informant_2$metadata$table$`_columns`, 2)
  expect_equal(informant_2$metadata$table$`_rows`, 6)

  expect_message(
    expect_warning(
      informant_3 <- create_informant(
        tbl = tbl,
        read_fn = function() pointblank::small_table
      )
    )
  )

  expect_equal(informant_3$metadata$table$`_columns`, 2)
  expect_equal(informant_3$metadata$table$`_rows`, 6)

  # Expect a warning if using `read_fn` to supply a target table
  expect_warning(
    create_informant(
      read_fn = pointblank::small_table
    )
  )

  # Expect that agent passed in to `create_informant()`
  # will use the agent's `tbl`, if available
  informant_4 <-
    create_informant(
      agent = create_agent(tbl = ~ pointblank::small_table)
    )

  expect_s3_class(informant_4$read_fn, "formula")
  expect_equal(
    as.character(informant_4$read_fn),
    c("~", "pointblank::small_table")
  )

  informant_5 <-
    create_informant(
      agent = create_agent(tbl = pointblank::small_table)
    )

  expect_null(informant_5$read_fn)
  expect_s3_class(informant_5$tbl, class(pointblank::small_table), exact = TRUE)
})
